<html>
<head><meta charset="utf-8"><title>what is NRVO? · t-compiler/wg-mir-opt · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/189540-t-compiler/wg-mir-opt/index.html">t-compiler/wg-mir-opt</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/189540-t-compiler/wg-mir-opt/topic/what.20is.20NRVO.3F.html">what is NRVO?</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="215057019"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/189540-t-compiler/wg-mir-opt/topic/what%20is%20NRVO%3F/near/215057019" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Noah Lev <a href="https://rust-lang.github.io/zulip_archive/stream/189540-t-compiler/wg-mir-opt/topic/what.20is.20NRVO.3F.html#215057019">(Oct 30 2020 at 04:56)</a>:</h4>
<p>What is NRVO? I've seen the <code>A-mir-opt-nrvo</code> label (description: "Fixed by NRVO") and I found the <a href="https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/nrvo/index.html"><code>rustc_mir::transform::nrvo</code> module</a>, but I can't seem to find any documentation on what it is.</p>



<a name="215057047"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/189540-t-compiler/wg-mir-opt/topic/what%20is%20NRVO%3F/near/215057047" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Noah Lev <a href="https://rust-lang.github.io/zulip_archive/stream/189540-t-compiler/wg-mir-opt/topic/what.20is.20NRVO.3F.html#215057047">(Oct 30 2020 at 04:58)</a>:</h4>
<p>I see a website that mentions C++ NRVO:</p>
<blockquote>
<p>This variant of copy elision is known as NRVO, "named return value optimization". In the initialization of an object, when the source object is a...</p>
</blockquote>
<p>But I can't find much and not any rust-specific docs</p>



<a name="215057087"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/189540-t-compiler/wg-mir-opt/topic/what%20is%20NRVO%3F/near/215057087" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Noah Lev <a href="https://rust-lang.github.io/zulip_archive/stream/189540-t-compiler/wg-mir-opt/topic/what.20is.20NRVO.3F.html#215057087">(Oct 30 2020 at 04:58)</a>:</h4>
<p>It looks like it was implemented by <span class="user-mention silent" data-user-id="118594">ecstatic-morse</span> in <a href="https://github.com/rust-lang/rust/issues/72205">#72205</a></p>



<a name="215059383"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/189540-t-compiler/wg-mir-opt/topic/what%20is%20NRVO%3F/near/215059383" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> vn-ki <a href="https://rust-lang.github.io/zulip_archive/stream/189540-t-compiler/wg-mir-opt/topic/what.20is.20NRVO.3F.html#215059383">(Oct 30 2020 at 06:01)</a>:</h4>
<p><a href="https://en.wikipedia.org/wiki/Copy_elision#Return_value_optimization">https://en.wikipedia.org/wiki/Copy_elision#Return_value_optimization</a></p>
<blockquote>
<p>In the context of the C++ programming language, return value optimization (RVO) is a compiler optimization that involves eliminating the temporary object created to hold a function's return value.</p>
</blockquote>
<p>I think rust uses the same definition here as C++</p>



<a name="215059627"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/189540-t-compiler/wg-mir-opt/topic/what%20is%20NRVO%3F/near/215059627" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Noah Lev <a href="https://rust-lang.github.io/zulip_archive/stream/189540-t-compiler/wg-mir-opt/topic/what.20is.20NRVO.3F.html#215059627">(Oct 30 2020 at 06:08)</a>:</h4>
<p>Should the label's description be changed? I'm not sure what it means by "Fixed by NRVO"</p>



<a name="215060102"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/189540-t-compiler/wg-mir-opt/topic/what%20is%20NRVO%3F/near/215060102" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> vn-ki <a href="https://rust-lang.github.io/zulip_archive/stream/189540-t-compiler/wg-mir-opt/topic/what.20is.20NRVO.3F.html#215060102">(Oct 30 2020 at 06:22)</a>:</h4>
<p>I'm still getting into this, so i maybe wrong. Someone more knowledgeable will correct me if I am :).</p>
<p>Take this example: <a href="https://github.com/rust-lang/rust/issues/57077">https://github.com/rust-lang/rust/issues/57077</a><br>
You can see that in the generated assembly for <code>call_by_val</code></p>
<div class="codehilite"><pre><span></span><code>    lea rdi, [rsp + 16]
    call    qword ptr [rip + SomeExternFun@GOTPCREL]
    movups  xmm0, xmmword ptr [rsp + 80]
    movaps  xmmword ptr [rsp + 160], xmm0
    movups  xmm0, xmmword ptr [rsp + 16]
    movups  xmm1, xmmword ptr [rsp + 32]
    movups  xmm2, xmmword ptr [rsp + 48]
    movups  xmm3, xmmword ptr [rsp + 64]
    movaps  xmmword ptr [rsp + 144], xmm3
    movaps  xmmword ptr [rsp + 128], xmm2
    movaps  xmmword ptr [rsp + 112], xmm1
    movaps  xmmword ptr [rsp + 96], xmm0
</code></pre></div>


<p>This is essentially a <code>memcpy</code> happening here. The memory space at <code>rsp+16</code> is passed to the external function and the memory from <code>rsp+16</code> to <code>rsp+96</code> is copied to <code>rsp+96</code>-<code>rsp+176</code>. If you think about it the optimisation that we can do here is to simply pass the memory once as the memory representation is the same and the copying of memory is unnecessary.</p>
<p>If you look at the <code>call_by_ref</code> you can see that it doesnt do this unnecessary copy.</p>
<p>If you try this same example in the playground today, you will not get a memcpy (both <code>call_by_ref</code> and <code>call_by_val</code> would be same).</p>
<p>Therefore, this has been fixed by the  Return Value Optimisation.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>